﻿using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;

namespace Jinndev.Localization {

    /// <summary>
    /// 本地化工具类
    /// </summary>
    public static class LocalizationUtil {

        //翻译替换指定标签的正则表达式
        public static readonly Regex TranslateLabelRegex = new Regex(@"<[^>]*>");   //得到整个标签
        public static readonly Regex TranslateKeyRegex = new Regex(@"(?<=<%)(.*?)(?=%>)");  //得到标签内部文本
        public static readonly string WrapFormat = "<%{0}%>";

        /// <summary>
        /// 相似语言列表，当指定语言不存在时，会尝试在相似语言列表内查找
        /// </summary>
        public static readonly Dictionary<SystemLanguage, SystemLanguage[]> SimilarLanguages = new Dictionary<SystemLanguage, SystemLanguage[]>();

        /// <summary>
        /// SystemLanguage到CultureInfo的映射
        /// </summary>
        public static readonly Dictionary<SystemLanguage, CultureInfo> LanguageToCulture = new Dictionary<SystemLanguage, CultureInfo>();

        /// <summary>
        /// 指定默认语言，当所有查找方式都没有找到时，最后使用该语言查找
        /// </summary>
        public static SystemLanguage DefaultLanguage = SystemLanguage.English;

        static LocalizationUtil() {
            SimilarLanguages.Add(SystemLanguage.Chinese, new SystemLanguage[] { SystemLanguage.ChineseSimplified, SystemLanguage.ChineseTraditional });
            SimilarLanguages.Add(SystemLanguage.ChineseSimplified, new SystemLanguage[] { SystemLanguage.Chinese, SystemLanguage.ChineseTraditional });
            SimilarLanguages.Add(SystemLanguage.ChineseTraditional, new SystemLanguage[] { SystemLanguage.Chinese, SystemLanguage.ChineseSimplified });

            LanguageToCulture.Add(SystemLanguage.English, CultureInfo.GetCultureInfo("en"));
            LanguageToCulture.Add(SystemLanguage.Chinese, CultureInfo.GetCultureInfo("zh"));
            LanguageToCulture.Add(SystemLanguage.ChineseSimplified, CultureInfo.GetCultureInfo("zh-CN"));
            LanguageToCulture.Add(SystemLanguage.ChineseTraditional, CultureInfo.GetCultureInfo("zh-TW"));
            LanguageToCulture.Add(SystemLanguage.Japanese, CultureInfo.GetCultureInfo("ja"));
            LanguageToCulture.Add(SystemLanguage.French, CultureInfo.GetCultureInfo("fr"));
            LanguageToCulture.Add(SystemLanguage.German, CultureInfo.GetCultureInfo("de"));
            LanguageToCulture.Add(SystemLanguage.Italian, CultureInfo.GetCultureInfo("it"));
            LanguageToCulture.Add(SystemLanguage.Korean, CultureInfo.GetCultureInfo("ko"));
            LanguageToCulture.Add(SystemLanguage.Russian, CultureInfo.GetCultureInfo("ru"));
            LanguageToCulture.Add(SystemLanguage.Spanish, CultureInfo.GetCultureInfo("es"));
        }

        public static bool TryGetCultureInfo(SystemLanguage language, out CultureInfo cultureInfo) {
            if (LanguageToCulture.TryGetValue(language, out cultureInfo)) {
                return cultureInfo != null;
            }
            return false;
        }

        /// <summary>
        /// 翻译各个&lt;%key%&gt;形式的标签<br/>
        /// 例如 "ABC&lt;%key1%&gt;DEF&lt;%key2%&gt;GHI"
        /// </summary>
        public static string TranslateRegex(string text) {
            if (text == null) {
                return null;
            }
            return TranslateLabelRegex.Replace(text, (m) => {
                string key = TranslateKeyRegex.Match(m.Value).Value;
                return LocalizationManager.Get(key, true);
            });
        }

        public static string WrapRegex(string key) {
            return string.Format(WrapFormat, key);
        }

        public static IEnumerable<string> WrapRegex(IEnumerable<string> keys) {
            List<string> result = new List<string>();
            if (keys != null) {
                foreach (string key in keys) {
                    result.Add(WrapRegex(key));
                }
            }
            return result;
        }

        public static void SetLocalizedKey(this Text text, string key, params object[] args) {
            SetLocalizedFormat(text, WrapRegex(key), args);
        }

        public static void SetLocalizedFormat(this Text text, string format, params object[] args) {
            LocalizationText localizationText = text.gameObject.GetComponent<LocalizationText>();
            if (localizationText == null) {
                localizationText = text.gameObject.AddComponent<LocalizationText>();
                localizationText.initWithText = false;
            }
            localizationText.SetText(format, args);
        }

        /// <summary>
        /// 获得语言简称
        /// </summary>
        public static string GetAbbreviation(SystemLanguage language) {
            if (TryGetCultureInfo(language, out CultureInfo cultureInfo)) {
                return cultureInfo.Name;
            }
            return null;
        }

        /// <summary>
        /// 在指定文件内找到与指定语言最接近的本地化配置文件
        /// </summary>
        public static string FindClosestFile(SystemLanguage language, string dir, string fileNamePattern) {
            if (!ResourceManager.DirectoryExists(dir)) {
                Debug.LogError($"Directory dosen't exist: '{dir}'");
                return null;
            }

            // 文件名索引
            string[] files = ResourceManager.GetFiles(dir);
            List<string> fileNames = new List<string>(files.Length);
            foreach (string file in files) {
                fileNames.Add(Path.GetFileName(file));
            }

            // 直接查找
            if (Exists(language, fileNames, dir, fileNamePattern, out string filePath)) {
                return filePath;
            }

            // 查找相似语言
            if (SimilarLanguages.TryGetValue(language, out SystemLanguage[] similarLanguages)) {
                for (int i = 0; i < similarLanguages.Length; i++) {
                    if (Exists(similarLanguages[i], fileNames, dir, fileNamePattern, out filePath)) {
                        return filePath;
                    }
                }
            }

            // 使用默认语言
            if (Exists(DefaultLanguage, fileNames, dir, fileNamePattern, out filePath)) {
                return filePath;
            }
            return null;
        }

        private static bool Exists(SystemLanguage language, List<string> fileNames, string dir, string fileNamePattern, out string filePath) {
            // 查找简称
            string abbreviation = GetAbbreviation(language);
            if (abbreviation != null && Exists(abbreviation, fileNames, dir, fileNamePattern, out filePath)) {
                return true;
            }
            // 查找全称
            return Exists(language.ToString(), fileNames, dir, fileNamePattern, out filePath);
        }

        private static bool Exists(string language, List<string> fileNames, string dir, string fileNamePattern, out string filePath) {
            string fileName = string.Format(fileNamePattern, language);
            if (fileNames.Contains(fileName)) {
                filePath = Path.Combine(dir, fileName);
                return true;
            }
            filePath = null;
            return false;
        }

    }

}
